import AppKit
import Commander
import CoreGraphics
import Foundation
import PeekabooCore
import PeekabooFoundation

// Logger for window command debugging

/// Manipulate application windows with various actions
@MainActor
struct WindowCommand: ParsableCommand {
    static let commandDescription = CommandDescription(
        commandName: "window",
        abstract: "Manipulate application windows",
        discussion: """
        SYNOPSIS:
          peekaboo window SUBCOMMAND [OPTIONS]

        DESCRIPTION:
          Provides window manipulation capabilities including closing, minimizing,
          maximizing, moving, resizing, and focusing windows.

        EXAMPLES:
          # Close a window
          peekaboo window close --app Safari
          peekaboo window close --app Safari --window-title "GitHub"

          # Minimize/maximize windows
          peekaboo window minimize --app Finder
          peekaboo window maximize --app Terminal

          # Move and resize windows
          peekaboo window move --app TextEdit --x 100 --y 100
          peekaboo window resize --app Safari --width 1200 --height 800
          peekaboo window set-bounds --app Chrome --x 50 --y 50 --width 1024 --height 768

          # Focus a window
          peekaboo window focus --app "Visual Studio Code"
          peekaboo window focus --app Safari --window-title "Apple"

          # List windows (convenience shortcut)
          peekaboo window list --app Safari

        SUBCOMMANDS:
          close         Close a window
          minimize      Minimize a window to the Dock
          maximize      Maximize a window (full screen)
          move          Move a window to a new position
          resize        Resize a window
          set-bounds    Set window position and size in one operation
          focus         Bring a window to the foreground
          list          List windows for an application

        OUTPUT FORMAT:
          Default output is human-readable text.
          Use --json-output for machine-readable JSON format.
        """,
        subcommands: [
            CloseSubcommand.self,
            MinimizeSubcommand.self,
            MaximizeSubcommand.self,
            MoveSubcommand.self,
            ResizeSubcommand.self,
            SetBoundsSubcommand.self,
            FocusSubcommand.self,
            WindowListSubcommand.self,
        ],
        showHelpOnEmptyInvocation: true
    )
}

// MARK: - Common Options

@MainActor
struct WindowIdentificationOptions: CommanderParsable, ApplicationResolvable {
    @Option(name: .long, help: "Target application name, bundle ID, or 'PID:12345'")
    var app: String?

    @Option(name: .long, help: "Target application by process ID")
    var pid: Int32?

    @Option(name: .long, help: "Target window by title (partial match supported)")
    var windowTitle: String?

    @Option(name: .long, help: "Target window by index (0-based, frontmost is 0)")
    var windowIndex: Int?

    enum CodingKeys: String, CodingKey {
        case app
        case pid
        case windowTitle
        case windowIndex
    }

    init() {}

    init(from decoder: any Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.app = try container.decodeIfPresent(String.self, forKey: .app)
        self.pid = try container.decodeIfPresent(Int32.self, forKey: .pid)
        self.windowTitle = try container.decodeIfPresent(String.self, forKey: .windowTitle)
        self.windowIndex = try container.decodeIfPresent(Int.self, forKey: .windowIndex)
    }

    func validate() throws {
        // Ensure we have some way to identify the window
        if self.app == nil && self.pid == nil {
            throw ValidationError("Either --app or --pid must be specified")
        }
    }

    /// Convert to WindowTarget for service layer
    func toWindowTarget() throws -> WindowTarget {
        // Convert to WindowTarget for service layer
        let appIdentifier = try self.resolveApplicationIdentifier()

        if let index = windowIndex {
            return .index(app: appIdentifier, index: index)
        } else if self.windowTitle != nil {
            // For title matching, we still need the app context
            // The service will handle finding the right window
            return .application(appIdentifier)
        } else {
            // Default to app's frontmost window
            return .application(appIdentifier)
        }
    }
}

// MARK: - Helper Functions

private func createWindowActionResult(
    action: String,
    success: Bool,
    windowInfo: ServiceWindowInfo?,
    appName: String? = nil
) -> WindowActionResult {
    let bounds: WindowBounds? = if let windowInfo {
        WindowBounds(
            x: Int(windowInfo.bounds.origin.x),
            y: Int(windowInfo.bounds.origin.y),
            width: Int(windowInfo.bounds.size.width),
            height: Int(windowInfo.bounds.size.height)
        )
    } else {
        nil
    }

    return WindowActionResult(
        action: action,
        success: success,
        app_name: appName ?? "Unknown",
        window_title: windowInfo?.title,
        new_bounds: bounds
    )
}

private func logWindowAction(
    action: String,
    appName: String?,
    windowInfo: ServiceWindowInfo?
) {
    let title = windowInfo?.title ?? "Unknown"
    let boundsDescription: String
    if let windowBounds = windowInfo?.bounds {
        let origin = "bounds=(\(Int(windowBounds.origin.x)),\(Int(windowBounds.origin.y)))"
        let size = "x(\(Int(windowBounds.size.width)),\(Int(windowBounds.size.height)))"
        boundsDescription = "\(origin)\(size)"
    } else {
        boundsDescription = "bounds=unknown"
    }
    AutomationEventLogger.log(
        .window,
        "\(action) app=\(appName ?? "Unknown") title=\(title) \(boundsDescription)"
    )
}

// MARK: - Subcommands

extension WindowCommand {
    @MainActor
    struct CloseSubcommand: ErrorHandlingCommand, OutputFormattable {
        @OptionGroup var windowOptions: WindowIdentificationOptions
        @RuntimeStorage private var runtime: CommandRuntime?

        private var resolvedRuntime: CommandRuntime {
            guard let runtime else {
                preconditionFailure("CommandRuntime must be configured before accessing runtime resources")
            }
            return runtime
        }

        private var services: any PeekabooServiceProviding { self.resolvedRuntime.services }
        private var logger: Logger { self.resolvedRuntime.logger }
        var outputLogger: Logger { self.logger }
        var jsonOutput: Bool { self.resolvedRuntime.configuration.jsonOutput }

        /// Resolve the target window, close it, and surface the outcome in JSON or text form.
        @MainActor
        mutating func run(using runtime: CommandRuntime) async throws {
            self.runtime = runtime
            self.logger.setJsonOutputMode(self.jsonOutput)

            do {
                try self.windowOptions.validate()
                let target = self.windowOptions.createTarget()

                // Get window info before action
                let windows = try await WindowServiceBridge.listWindows(
                    windows: self.services.windows,
                    target: self.windowOptions.toWindowTarget()
                )
                let windowInfo = self.windowOptions.selectWindow(from: windows)
                let appName = self.windowOptions.app ?? "Unknown"

                // Perform the action
                try await WindowServiceBridge.closeWindow(windows: self.services.windows, target: target)

                logWindowAction(
                    action: "close",
                    appName: appName,
                    windowInfo: windowInfo
                )

                let data = createWindowActionResult(
                    action: "close",
                    success: true,
                    windowInfo: windowInfo,
                    appName: appName
                )

                output(data) {
                    print("Successfully closed window '\(windowInfo?.title ?? "Untitled")' of \(appName)")
                }

            } catch {
                handleError(error)
                throw ExitCode(1)
            }
        }
    }

    @MainActor
    struct MinimizeSubcommand: ErrorHandlingCommand, OutputFormattable {
        @OptionGroup var windowOptions: WindowIdentificationOptions
        @RuntimeStorage private var runtime: CommandRuntime?

        private var resolvedRuntime: CommandRuntime {
            guard let runtime else {
                preconditionFailure("CommandRuntime must be configured before accessing runtime resources")
            }
            return runtime
        }

        private var services: any PeekabooServiceProviding { self.resolvedRuntime.services }
        private var logger: Logger { self.resolvedRuntime.logger }
        var outputLogger: Logger { self.logger }
        var jsonOutput: Bool { self.resolvedRuntime.configuration.jsonOutput }

        /// Resolve the target window, minimize it to the Dock, and report the action.
        @MainActor
        mutating func run(using runtime: CommandRuntime) async throws {
            self.runtime = runtime
            self.logger.setJsonOutputMode(self.jsonOutput)

            do {
                try self.windowOptions.validate()
                let target = self.windowOptions.createTarget()

                // Get window info before action
                let windows = try await WindowServiceBridge.listWindows(
                    windows: self.services.windows,
                    target: self.windowOptions.toWindowTarget()
                )
                let windowInfo = self.windowOptions.selectWindow(from: windows)
                let appName = self.windowOptions.app ?? "Unknown"

                // Perform the action
                try await WindowServiceBridge.minimizeWindow(windows: self.services.windows, target: target)
                logWindowAction(
                    action: "minimize",
                    appName: appName,
                    windowInfo: windowInfo
                )

                let data = createWindowActionResult(
                    action: "minimize",
                    success: true,
                    windowInfo: windowInfo,
                    appName: appName
                )

                output(data) {
                    print("Successfully minimized window '\(windowInfo?.title ?? "Untitled")' of \(appName)")
                }

            } catch {
                handleError(error)
                throw ExitCode(1)
            }
        }
    }

    @MainActor
    struct MaximizeSubcommand: ErrorHandlingCommand, OutputFormattable {
        @OptionGroup var windowOptions: WindowIdentificationOptions
        @RuntimeStorage private var runtime: CommandRuntime?

        private var resolvedRuntime: CommandRuntime {
            guard let runtime else {
                preconditionFailure("CommandRuntime must be configured before accessing runtime resources")
            }
            return runtime
        }

        private var services: any PeekabooServiceProviding { self.resolvedRuntime.services }
        private var logger: Logger { self.resolvedRuntime.logger }
        var outputLogger: Logger { self.logger }
        var jsonOutput: Bool { self.resolvedRuntime.configuration.jsonOutput }

        /// Expand the resolved window to fill the available screen real estate and share the updated frame.
        @MainActor
        mutating func run(using runtime: CommandRuntime) async throws {
            self.runtime = runtime
            self.logger.setJsonOutputMode(self.jsonOutput)

            do {
                try self.windowOptions.validate()
                let target = self.windowOptions.createTarget()

                // Get window info before action
                let windows = try await WindowServiceBridge.listWindows(
                    windows: self.services.windows,
                    target: self.windowOptions.toWindowTarget()
                )
                let windowInfo = self.windowOptions.selectWindow(from: windows)
                let appName = self.windowOptions.app ?? "Unknown"

                // Perform the action
                try await WindowServiceBridge.maximizeWindow(windows: self.services.windows, target: target)
                logWindowAction(
                    action: "maximize",
                    appName: appName,
                    windowInfo: windowInfo
                )

                let data = createWindowActionResult(
                    action: "maximize",
                    success: true,
                    windowInfo: windowInfo,
                    appName: appName
                )

                output(data) {
                    print("Successfully maximized window '\(windowInfo?.title ?? "Untitled")' of \(appName)")
                }

            } catch {
                handleError(error)
                throw ExitCode(1)
            }
        }
    }

    @MainActor
    struct FocusSubcommand: ErrorHandlingCommand, OutputFormattable {
        @OptionGroup var windowOptions: WindowIdentificationOptions

        @OptionGroup var focusOptions: FocusCommandOptions
        @RuntimeStorage private var runtime: CommandRuntime?

        private var resolvedRuntime: CommandRuntime {
            guard let runtime else {
                preconditionFailure("CommandRuntime must be configured before accessing runtime resources")
            }
            return runtime
        }

        private var services: any PeekabooServiceProviding { self.resolvedRuntime.services }
        private var logger: Logger { self.resolvedRuntime.logger }
        var outputLogger: Logger { self.logger }
        var jsonOutput: Bool { self.resolvedRuntime.configuration.jsonOutput }

        /// Focus the targeted window, handling Space switches or relocation according to the provided options.
        @MainActor
        mutating func run(using runtime: CommandRuntime) async throws {
            self.runtime = runtime
            self.logger.debug("FocusSubcommand.run() called")
            self.logger.setJsonOutputMode(self.jsonOutput)

            do {
                self.logger.debug("About to validate window options")
                try self.windowOptions.validate()
                self.logger.debug("Window options validated")
                let target = self.windowOptions.createTarget()
                self.logger.debug("Target created: \(target)")

                // Get window info before action
                let windows = try await WindowServiceBridge.listWindows(
                    windows: self.services.windows,
                    target: self.windowOptions.toWindowTarget()
                )
                self.logger.debug("Found \(windows.count) windows")
                let windowInfo = self.windowOptions.selectWindow(from: windows)
                let appName = self.windowOptions.app ?? "Unknown"

                // Check if we found any windows
                guard !windows.isEmpty else {
                    throw PeekabooError.windowNotFound(criteria: "No windows found for \(appName)")
                }

                // Use enhanced focus with space support
                if let windowID = windowInfo?.windowID {
                    try await ensureFocused(
                        windowID: CGWindowID(windowID),
                        applicationName: self.windowOptions.app,
                        windowTitle: self.windowOptions.windowTitle,
                        options: self.focusOptions.asFocusOptions,
                        services: self.services
                    )
                } else {
                    // Fallback to regular focus if no window ID
                    try await WindowServiceBridge.focusWindow(windows: self.services.windows, target: target)
                }

                let refreshedWindowInfo = await self.windowOptions.refetchWindowInfo(
                    services: self.services,
                    logger: self.logger,
                    context: "window-focus"
                )
                let finalWindowInfo = refreshedWindowInfo ?? windowInfo
                logWindowAction(
                    action: "focus",
                    appName: appName,
                    windowInfo: finalWindowInfo
                )

                let data = createWindowActionResult(
                    action: "focus",
                    success: true,
                    windowInfo: finalWindowInfo,
                    appName: appName
                )

                output(data) {
                    var message = "Successfully focused window '\(finalWindowInfo?.title ?? "Untitled")' of \(appName)"
                    if self.focusOptions.bringToCurrentSpace {
                        message += " (moved to current Space)"
                    }
                    print(message)
                }

            } catch {
                handleError(error)
                throw ExitCode(1)
            }
        }
    }

    // MARK: - Move Command

    @MainActor
    struct MoveSubcommand: ErrorHandlingCommand, OutputFormattable {
        @OptionGroup var windowOptions: WindowIdentificationOptions

        @Option(name: .customShort("x", allowingJoined: false), help: "New X coordinate")
        var x: Int

        @Option(name: .customShort("y", allowingJoined: false), help: "New Y coordinate")
        var y: Int
        @RuntimeStorage private var runtime: CommandRuntime?

        private var resolvedRuntime: CommandRuntime {
            guard let runtime else {
                preconditionFailure("CommandRuntime must be configured before accessing runtime resources")
            }
            return runtime
        }

        private var services: any PeekabooServiceProviding { self.resolvedRuntime.services }
        private var logger: Logger { self.resolvedRuntime.logger }
        var outputLogger: Logger { self.logger }
        var jsonOutput: Bool { self.resolvedRuntime.configuration.jsonOutput }

        /// Move the window to the absolute screen coordinates provided by the user.
        @MainActor
        mutating func run(using runtime: CommandRuntime) async throws {
            self.runtime = runtime
            self.logger.setJsonOutputMode(self.jsonOutput)

            do {
                try self.windowOptions.validate()
                let target = self.windowOptions.createTarget()

                // Get window info
                let windows = try await WindowServiceBridge.listWindows(
                    windows: self.services.windows,
                    target: self.windowOptions.toWindowTarget()
                )
                let windowInfo = self.windowOptions.selectWindow(from: windows)
                let appName = self.windowOptions.app ?? "Unknown"

                // Move the window
                let newOrigin = CGPoint(x: x, y: y)
                try await WindowServiceBridge.moveWindow(windows: self.services.windows, target: target, to: newOrigin)

                // Create result with new bounds
                let updatedInfo = windowInfo.map { info in
                    ServiceWindowInfo(
                        windowID: info.windowID,
                        title: info.title,
                        bounds: CGRect(origin: newOrigin, size: info.bounds.size),
                        isMinimized: info.isMinimized,
                        isMainWindow: info.isMainWindow,
                        windowLevel: info.windowLevel,
                        alpha: info.alpha,
                        index: info.index
                    )
                }

                let refreshedWindowInfo = await self.windowOptions.refetchWindowInfo(
                    services: self.services,
                    logger: self.logger,
                    context: "window-move"
                )
                let finalWindowInfo = refreshedWindowInfo ?? updatedInfo ?? windowInfo

                logWindowAction(
                    action: "move",
                    appName: appName,
                    windowInfo: finalWindowInfo
                )

                let data = createWindowActionResult(
                    action: "move",
                    success: true,
                    windowInfo: finalWindowInfo,
                    appName: appName
                )

                output(data) {
                    print(
                        "Successfully moved window '\(finalWindowInfo?.title ?? "Untitled")' to (\(self.x), \(self.y))"
                    )
                }

            } catch {
                handleError(error)
                throw ExitCode(1)
            }
        }
    }

    // MARK: - Resize Command

    @MainActor
    struct ResizeSubcommand: ErrorHandlingCommand, OutputFormattable {
        @OptionGroup var windowOptions: WindowIdentificationOptions

        @Option(name: .customShort("w", allowingJoined: false), help: "New width")
        var width: Int

        @Option(name: .long, help: "New height")
        var height: Int
        @RuntimeStorage private var runtime: CommandRuntime?

        private var resolvedRuntime: CommandRuntime {
            guard let runtime else {
                preconditionFailure("CommandRuntime must be configured before accessing runtime resources")
            }
            return runtime
        }

        private var services: any PeekabooServiceProviding { self.resolvedRuntime.services }
        private var logger: Logger { self.resolvedRuntime.logger }
        var outputLogger: Logger { self.logger }
        var jsonOutput: Bool { self.resolvedRuntime.configuration.jsonOutput }

        /// Resize the window to the supplied dimensions, preserving its origin.
        @MainActor
        mutating func run(using runtime: CommandRuntime) async throws {
            self.runtime = runtime
            self.logger.setJsonOutputMode(self.jsonOutput)

            do {
                try self.windowOptions.validate()
                let target = self.windowOptions.createTarget()

                // Get window info
                let windows = try await WindowServiceBridge.listWindows(
                    windows: self.services.windows,
                    target: self.windowOptions.toWindowTarget()
                )
                let windowInfo = self.windowOptions.selectWindow(from: windows)
                let appName = self.windowOptions.app ?? "Unknown"

                // Resize the window
                let newSize = CGSize(width: width, height: height)
                try await WindowServiceBridge.resizeWindow(windows: self.services.windows, target: target, to: newSize)

                let refreshedWindowInfo = await self.windowOptions.refetchWindowInfo(
                    services: self.services,
                    logger: self.logger,
                    context: "window-resize"
                )
                let finalWindowInfo = refreshedWindowInfo ?? windowInfo
                logWindowAction(
                    action: "resize",
                    appName: appName,
                    windowInfo: finalWindowInfo
                )

                let data = createWindowActionResult(
                    action: "resize",
                    success: true,
                    windowInfo: finalWindowInfo,
                    appName: appName
                )

                output(data) {
                    let title = finalWindowInfo?.title ?? "Untitled"
                    print("Successfully resized window '\(title)' to \(self.width)x\(self.height)")
                }

            } catch {
                handleError(error)
                throw ExitCode(1)
            }
        }
    }

    // MARK: - Set Bounds Command

    @MainActor
    struct SetBoundsSubcommand: ErrorHandlingCommand, OutputFormattable {
        @OptionGroup var windowOptions: WindowIdentificationOptions

        @Option(name: .customShort("x", allowingJoined: false), help: "New X coordinate")
        var x: Int

        @Option(name: .customShort("y", allowingJoined: false), help: "New Y coordinate")
        var y: Int

        @Option(name: .customShort("w", allowingJoined: false), help: "New width")
        var width: Int

        @Option(name: .long, help: "New height")
        var height: Int
        @RuntimeStorage private var runtime: CommandRuntime?

        private var resolvedRuntime: CommandRuntime {
            guard let runtime else {
                preconditionFailure("CommandRuntime must be configured before accessing runtime resources")
            }
            return runtime
        }

        private var services: any PeekabooServiceProviding { self.resolvedRuntime.services }
        private var logger: Logger { self.resolvedRuntime.logger }
        var outputLogger: Logger { self.logger }
        var jsonOutput: Bool { self.resolvedRuntime.configuration.jsonOutput }

        /// Set both position and size for the window in a single operation, then confirm the new bounds.
        @MainActor
        mutating func run(using runtime: CommandRuntime) async throws {
            self.runtime = runtime
            self.logger.setJsonOutputMode(self.jsonOutput)

            do {
                try self.windowOptions.validate()
                let target = self.windowOptions.createTarget()

                // Get window info
                let windows = try await WindowServiceBridge.listWindows(
                    windows: self.services.windows,
                    target: self.windowOptions.toWindowTarget()
                )
                let windowInfo = self.windowOptions.selectWindow(from: windows)
                let appName = self.windowOptions.app ?? "Unknown"

                // Set bounds
                let newBounds = CGRect(x: x, y: y, width: width, height: height)
                try await WindowServiceBridge.setWindowBounds(
                    windows: self.services.windows,
                    target: target,
                    bounds: newBounds
                )

                let refreshedWindowInfo = await self.windowOptions.refetchWindowInfo(
                    services: self.services,
                    logger: self.logger,
                    context: "window-set-bounds"
                )
                let finalWindowInfo = refreshedWindowInfo ?? windowInfo
                logWindowAction(
                    action: "set-bounds",
                    appName: appName,
                    windowInfo: finalWindowInfo
                )

                let data = createWindowActionResult(
                    action: "set-bounds",
                    success: true,
                    windowInfo: finalWindowInfo,
                    appName: appName
                )

                output(data) {
                    let title = finalWindowInfo?.title ?? "Untitled"
                    let boundsDescription = "(\(self.x), \(self.y)) \(self.width)x\(self.height)"
                    print("Successfully set window '\(title)' bounds to \(boundsDescription)")
                }

            } catch {
                handleError(error)
                throw ExitCode(1)
            }
        }
    }

    // MARK: - List Command

    @MainActor
    struct WindowListSubcommand: ErrorHandlingCommand, OutputFormattable, ApplicationResolvable {
        @Option(name: .long, help: "Target application name, bundle ID, or 'PID:12345'")
        var app: String?

        @Option(name: .long, help: "Target application by process ID")
        var pid: Int32?
        @RuntimeStorage private var runtime: CommandRuntime?

        private var resolvedRuntime: CommandRuntime {
            guard let runtime else {
                preconditionFailure("CommandRuntime must be configured before accessing runtime resources")
            }
            return runtime
        }

        private var services: any PeekabooServiceProviding { self.resolvedRuntime.services }
        private var logger: Logger { self.resolvedRuntime.logger }
        var outputLogger: Logger { self.logger }
        var jsonOutput: Bool { self.resolvedRuntime.configuration.jsonOutput }

        @Flag(name: .long, help: "Group windows by Space (virtual desktop)")
        var groupBySpace = false

        /// List windows for the target application and optionally organize them by Space.
        @MainActor
        mutating func run(using runtime: CommandRuntime) async throws {
            self.runtime = runtime
            self.logger.setJsonOutputMode(self.jsonOutput)

            do {
                let appIdentifier = try self.resolveApplicationIdentifier()
                // First find the application to get its info
                let appInfo = try await self.services.applications.findApplication(identifier: appIdentifier)

                let target = WindowTarget.application(appIdentifier)
                let rawWindows = try await WindowServiceBridge.listWindows(
                    windows: self.services.windows,
                    target: target
                )
                let windows = WindowFilterHelper.filter(
                    windows: rawWindows,
                    appIdentifier: appIdentifier,
                    mode: .list,
                    logger: self.logger
                )

                // Convert ServiceWindowInfo to WindowInfo for consistency
                let windowInfos = windows.map { window in
                    WindowInfo(
                        window_title: window.title,
                        window_id: UInt32(window.windowID),
                        window_index: window.index,
                        bounds: WindowBounds(
                            x: Int(window.bounds.origin.x),
                            y: Int(window.bounds.origin.y),
                            width: Int(window.bounds.size.width),
                            height: Int(window.bounds.size.height)
                        ),
                        is_on_screen: window.isOnScreen
                    )
                }

                // Use PeekabooCore's WindowListData
                let data = WindowListData(
                    windows: windowInfos,
                    target_application_info: TargetApplicationInfo(
                        app_name: appInfo.name,
                        bundle_id: appInfo.bundleIdentifier,
                        pid: appInfo.processIdentifier
                    )
                )

                output(data) {
                    print("\(data.target_application_info.app_name) has \(data.windows.count) window(s):")

                    if self.groupBySpace {
                        // Group windows by space
                        var windowsBySpace: [UInt64?: [(window: ServiceWindowInfo, index: Int)]] = [:]

                        for window in windows {
                            let spaceID = window.spaceID
                            windowsBySpace[spaceID, default: []].append((window, window.index))
                        }

                        // Sort spaces by ID (nil first for windows not on any space)
                        let sortedSpaces = windowsBySpace.keys.sorted { a, b in
                            switch (a, b) {
                            case (nil, nil): false
                            case (nil, _): true
                            case (_, nil): false
                            case let (a?, b?): a < b
                            }
                        }

                        // Print grouped windows
                        for spaceID in sortedSpaces {
                            if let spaceID {
                                let spaceName = windowsBySpace[spaceID]?.first?.window.spaceName ?? "Space \(spaceID)"
                                print("\n  Space: \(spaceName) [ID: \(spaceID)]")
                            } else {
                                print("\n  No Space:")
                            }

                            for (window, index) in windowsBySpace[spaceID] ?? [] {
                                let status = window.isMinimized ? " [minimized]" : ""
                                print("    [\(index)] \"\(window.title)\"\(status)")
                                let origin = window.bounds.origin
                                print("         Position: (\(Int(origin.x)), \(Int(origin.y)))")
                                print(
                                    "         Size: \(Int(window.bounds.size.width))x\(Int(window.bounds.size.height))"
                                )
                            }
                        }
                    } else {
                        // Original flat list
                        for window in data.windows {
                            let index = window.window_index ?? 0
                            let status = (window.is_on_screen == false) ? " [minimized]" : ""
                            print("  [\(index)] \"\(window.window_title)\"\(status)")
                            if let bounds = window.bounds {
                                print("       Position: (\(bounds.x), \(bounds.y))")
                                print("       Size: \(bounds.width)x\(bounds.height)")
                            }
                        }
                    }
                }

            } catch {
                handleError(error)
                throw ExitCode(1)
            }
        }
    }
}

// MARK: - Response Types

struct WindowActionResult: Codable {
    let action: String
    let success: Bool
    let app_name: String
    let window_title: String?
    let new_bounds: WindowBounds?
}

// Using PeekabooCore.WindowListData for consistency

// MARK: - Subcommand Conformances

@MainActor
extension WindowCommand.MoveSubcommand: ParsableCommand {
    nonisolated(unsafe) static var commandDescription: CommandDescription {
        MainActorCommandDescription.describe {
            CommandDescription(commandName: "move", abstract: "Move a window to a new position")
        }
    }
}

extension WindowCommand.MoveSubcommand: AsyncRuntimeCommand {}

@MainActor
extension WindowCommand.ResizeSubcommand: ParsableCommand {
    nonisolated(unsafe) static var commandDescription: CommandDescription {
        MainActorCommandDescription.describe {
            CommandDescription(commandName: "resize", abstract: "Resize a window")
        }
    }
}

extension WindowCommand.ResizeSubcommand: AsyncRuntimeCommand {}

@MainActor
extension WindowCommand.SetBoundsSubcommand: ParsableCommand {
    nonisolated(unsafe) static var commandDescription: CommandDescription {
        MainActorCommandDescription.describe {
            CommandDescription(commandName: "set-bounds", abstract: "Set window position and size in one operation")
        }
    }
}

extension WindowCommand.SetBoundsSubcommand: AsyncRuntimeCommand {}

@MainActor
extension WindowCommand.WindowListSubcommand: ParsableCommand {
    nonisolated(unsafe) static var commandDescription: CommandDescription {
        MainActorCommandDescription.describe {
            CommandDescription(commandName: "list", abstract: "List windows for an application")
        }
    }
}

extension WindowCommand.WindowListSubcommand: AsyncRuntimeCommand {}

@MainActor
extension WindowCommand.CloseSubcommand: ParsableCommand {
    nonisolated(unsafe) static var commandDescription: CommandDescription {
        MainActorCommandDescription.describe {
            CommandDescription(commandName: "close", abstract: "Close a window")
        }
    }
}

extension WindowCommand.CloseSubcommand: AsyncRuntimeCommand {}

@MainActor
extension WindowCommand.MinimizeSubcommand: ParsableCommand {
    nonisolated(unsafe) static var commandDescription: CommandDescription {
        MainActorCommandDescription.describe {
            CommandDescription(commandName: "minimize", abstract: "Minimize a window to the Dock")
        }
    }
}

extension WindowCommand.MinimizeSubcommand: AsyncRuntimeCommand {}

@MainActor
extension WindowCommand.MaximizeSubcommand: ParsableCommand {
    nonisolated(unsafe) static var commandDescription: CommandDescription {
        MainActorCommandDescription.describe {
            CommandDescription(commandName: "maximize", abstract: "Maximize a window (full screen)")
        }
    }
}

extension WindowCommand.MaximizeSubcommand: AsyncRuntimeCommand {}

@MainActor
extension WindowCommand.FocusSubcommand: ParsableCommand {
    nonisolated(unsafe) static var commandDescription: CommandDescription {
        MainActorCommandDescription.describe {
            CommandDescription(
                commandName: "focus",
                abstract: "Bring a window to the foreground",
                discussion: """
                Focus brings a window to the foreground and activates its application.

                Space Support:
                By default, if the window is on a different Space (virtual desktop),
                the focus command will switch to that Space. You can control this
                behavior with the --space-switch and --move-here options.

                Examples:
                peekaboo window focus --app Safari
                peekaboo window focus --app "Visual Studio Code" --window-title "main.swift"
                peekaboo window focus --app Terminal --no-space-switch
                peekaboo window focus --app Finder --move-here
                """
            )
        }
    }
}

extension WindowCommand.FocusSubcommand: AsyncRuntimeCommand {}

// MARK: - Commander Binding

@MainActor
extension WindowCommand.CloseSubcommand: CommanderBindableCommand {
    mutating func applyCommanderValues(_ values: CommanderBindableValues) throws {
        self.windowOptions = try values.makeWindowOptions()
    }
}

@MainActor
extension WindowCommand.MinimizeSubcommand: CommanderBindableCommand {
    mutating func applyCommanderValues(_ values: CommanderBindableValues) throws {
        self.windowOptions = try values.makeWindowOptions()
    }
}

@MainActor
extension WindowCommand.MaximizeSubcommand: CommanderBindableCommand {
    mutating func applyCommanderValues(_ values: CommanderBindableValues) throws {
        self.windowOptions = try values.makeWindowOptions()
    }
}

@MainActor
extension WindowCommand.FocusSubcommand: CommanderBindableCommand {
    mutating func applyCommanderValues(_ values: CommanderBindableValues) throws {
        self.windowOptions = try values.makeWindowOptions()
        self.focusOptions = try values.makeFocusOptions()
    }
}

@MainActor
extension WindowCommand.MoveSubcommand: CommanderBindableCommand {
    mutating func applyCommanderValues(_ values: CommanderBindableValues) throws {
        self.windowOptions = try values.makeWindowOptions()
        self.x = try values.requireOption("x", as: Int.self)
        self.y = try values.requireOption("y", as: Int.self)
    }
}

@MainActor
extension WindowCommand.ResizeSubcommand: CommanderBindableCommand {
    mutating func applyCommanderValues(_ values: CommanderBindableValues) throws {
        self.windowOptions = try values.makeWindowOptions()
        self.width = try values.requireOption("width", as: Int.self)
        self.height = try values.requireOption("height", as: Int.self)
    }
}

@MainActor
extension WindowCommand.SetBoundsSubcommand: CommanderBindableCommand {
    mutating func applyCommanderValues(_ values: CommanderBindableValues) throws {
        self.windowOptions = try values.makeWindowOptions()
        self.x = try values.requireOption("x", as: Int.self)
        self.y = try values.requireOption("y", as: Int.self)
        self.width = try values.requireOption("width", as: Int.self)
        self.height = try values.requireOption("height", as: Int.self)
    }
}

@MainActor
extension WindowCommand.WindowListSubcommand: CommanderBindableCommand {
    mutating func applyCommanderValues(_ values: CommanderBindableValues) throws {
        self.app = values.singleOption("app")
        self.pid = try values.decodeOption("pid", as: Int32.self)
    }
}

// MARK: - Commander Helpers
